﻿#include "PolyCheck.h"
#include "AmPackAlgPlugin.h"
#include "files/syslog.h" 
#include <qfile.h>
#include <ActiveQt/qaxobject.h>
#include <string>
#include <qdir.h>
#include <QtConcurrent/qtconcurrentrun.h>
#include <qtextcodec.h>
#include "clscalculateab.h"
#include <Windows.h>
#include <TlHelp32.h>

#include "ColDefine.h"


//#include <pcl/point_types.h>
//#include <pcl/io/pcd_io.h>
//#include <pcl/filters/statistical_outlier_removal.h>

//MARK值分段，左开右闭
#define MAIN_MARK_START_RANGE	0
#define MAIN_MARK_END_RANGE		4
#define SUB_MARK_START_RANGE	300
#define SUB_MARK_END_RANGE		304
#define SUB_END_RANGE			600
#define FULL_POINTCLOUD_MARK	"9999"
#define FIRST_CHECK_MARK		9998

#define TIME_TEST
#ifdef TIME_TEST
# define TIME_START	auto startTime = std::chrono::system_clock::now();
# define TIME_END(text)	auto endTime = std::chrono::system_clock::now();\
						auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();\
						std::cout << text << duration << std::endl;\
						SysLog::log(LOG_ALGO, QString::fromStdString(text) + QString::number(duration));
#endif // DEBUG

#define USE_NORM_SPACE_SAMPLING	    0   //使用法向采样

Q_DECLARE_METATYPE(cv::Mat)

bool WriteCloud3D(const char* filename, cv::Mat cloud)
{
	auto startTime = std::chrono::system_clock::now();
	FILE* fp;
	fopen_s(&fp, filename, "a");
	auto startTime2 = std::chrono::system_clock::now();
	auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(startTime2 - startTime).count();
	//std::cout << "open" << duration << "\n";
	if (NULL == fp)
	{
		SysLog::log(LOG_ALARM, QString(filename) + " fail!");
		return false;
	}

	for (int h = 0; h < cloud.cols; h++)
	{
		float x = cloud.at<float>(0, h);
		if (x != x)continue;
		float y = cloud.at<float>(1, h);
		float z = cloud.at<float>(2, h);
		//float gray = cloud.at<float>(3, h);
		//fprintf(fp, "%f %f %f %f\n", x, y, z, gray);
		fprintf(fp, "%f %f %f\n", x, y, z);
	}
	fclose(fp);
	auto startTime3 = std::chrono::system_clock::now();
	auto duration1 = std::chrono::duration_cast<std::chrono::milliseconds>(startTime3 - startTime).count();
	//std::cout << "write" << duration1 << "\n";
	return true;
}

void ReadCloud(const char* filename, cv::Mat& xyz)
{
	QFile inFile(filename);
	long size = 0;
	if (inFile.open(QIODevice::ReadOnly))
	{
		{
			QTextStream stream_text(&inFile);
			while (!stream_text.atEnd())
			{
				stream_text.readLine();
				size++;
			}
		}
		inFile.close();
	}
	inFile.open(QIODevice::ReadOnly);
	xyz = cv::Mat(4, size, CV_32FC1);
	QTextStream stream_text(&inFile);
	int i = 0;
	while (!stream_text.atEnd())
	{
		auto line = stream_text.readLine().split(" ");
		xyz.at<float>(0, i) = line.at(0).toFloat();
		xyz.at<float>(1, i) = line.at(1).toFloat();
		xyz.at<float>(2, i) = line.at(2).toFloat();
		xyz.at<float>(3, i) = 1;
		i++;
	}
	inFile.close();
}

DWORD FindProcessIDByName(const QString& processName)
{
	HANDLE hProcessSnap;
	PROCESSENTRY32 pe32;
	hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hProcessSnap == INVALID_HANDLE_VALUE)
	{
		return 0;
	}
	pe32.dwSize = sizeof(PROCESSENTRY32);
	if (!Process32First(hProcessSnap, &pe32))
	{
		CloseHandle(hProcessSnap);          // clean the snapshot object
		return 0;
	}
	DWORD processId = 0;
	std::list<std::wstring> prolist;
	do
	{
		prolist.push_back(std::wstring(pe32.szExeFile));
		if (0 == lstrcmpW(processName.toStdWString().c_str(), pe32.szExeFile))//进程名称
		{
			processId = pe32.th32ProcessID;//进程ID
			break;
		}
	} while (Process32Next(hProcessSnap, &pe32));
	CloseHandle(hProcessSnap);
	return processId;
}

AmPackAlgPlugin::AmPackAlgPlugin()
	:mpCalAB(new ClsCalculateAB)
	, mpPolyCheck(new PolyCheck)
{
	mfRandVal0 = 0;
	mfRandVal1 = 0;
	mfRandVal2 = 0;
	mbUseLocalData = false;

	srand(time(0));
	mnRandSeedIndex = int(rand() * 1000) % mvnRandSeed.size();
	mfOffsetX = 0;
	mfOffsetY = 0;
	mfOffsetZ = 0;
}

AmPackAlgPlugin::~AmPackAlgPlugin()
{
	SAFE_DELETE(mpPolyCheck);
	SAFE_DELETE(mpCalAB);
}

void AmPackAlgPlugin::detect(QVector<DetectResult_t>& vecResult, const QVector<ImageData_t>& images, QList<algoItemStruct>& params)
{
#ifdef TIME_TEST
	TIME_START;
#endif // TIME_TEST
	if (!images.size()) return;
	for (auto& image : images)
	{
		DetectResult_t detectRes;
		auto& firstMark = image.strAlgoMark;
		if (mAlgoMarkList.contains(firstMark))
		{
			int index = mPosMap.value(firstMark, QStringList() << firstMark).at(INDEX_COL).toInt();
			SysLog::log(LOG_ALGO, "AlgorithumPlugin index " + QString::number(index) + " mark " + firstMark);
			if (int enable_type = mPosMap.value(firstMark).at(ENABLE_COL).toInt(); enable_type > 0)
			{
				if (image.test_mode == 2)//首件master是2
				{
					FirstCheck(image, detectRes);
				}
				else if (bool isHigh = image.test_mode == 6;//低小车是0，高小车是6，如果还有跑标定块的话那就是3
					(image.test_mode == 0 && enable_type == 1) ||
					(image.test_mode == 6 && enable_type >= 1))
				{
					if ((index > MAIN_MARK_START_RANGE && index <= MAIN_MARK_END_RANGE)
						|| (index > SUB_MARK_START_RANGE && index <= SUB_MARK_END_RANGE))//精定位
					{
						JingDingWei(image, detectRes, index, isHigh);
					}
					else if ((index > MAIN_MARK_END_RANGE && index <= SUB_MARK_START_RANGE)
						|| (index > SUB_MARK_END_RANGE && index <= SUB_END_RANGE))//一般点位
					{
						YiBanDianWei(image, detectRes, isHigh);
					}
					else if (index == QString(FULL_POINTCLOUD_MARK).toInt())//整体
					{
						Polyworks(image, detectRes, isHigh);
						SetParam();
					}
					else
					{
						qDebug() << "Unknown mark";
						SysLog::log(LOG_ALARM, tr("AlgorithumPlugin: Unknown mark") + firstMark);
					}
				}
				else
				{
					SysLog::log(LOG_ALARM, tr("AlgorithumPlugin: Unknown test mode") + firstMark);
				}
			}
			else
			{
				SysLog::log(LOG_ALARM, tr("AlgorithumPlugin: Disabled mark") + firstMark);
			}
		}
		else
		{
			qDebug() << "Unknown mark";
			SysLog::log(LOG_ALARM, tr("AlgorithumPlugin: Unknown mark") + firstMark);
		}
		detectRes.strAlgoMark = image.strAlgoMark;
		vecResult.push_back(detectRes);
	}
#ifdef TIME_TEST
	TIME_END("mark :" + images.at(0).strAlgoMark.toStdString() + " detect time:");
#endif // TIME_TEST	


}

bool AmPackAlgPlugin::algoOperate(emAlgoOperate operate)
{
	if (operate != emAlgoOperate::ALGO_OPERATE_INIT && operate != emAlgoOperate::ALGO_OPERATE_PARAM_CHANGE)
		return false;
	bool ret = true;
	if (mCurrentFormula == g_pSetting->getFormulaPath())
	{
		return true;
	}
	mCurrentFormula = g_pSetting->getFormulaPath();
	for (const auto& item : g_pAlgoXml->getAllItem())
		if (item.item == "3DSolution")
		{
			for (const auto& subItem : item.subItems)
				if (subItem.item == "AlgParam")
				{
					for (const auto& param : subItem.paras)
						mAlgParam[param.name] = param.value;
					break;
				}
			break;
		}

	mpCalAB->SetParams(mAlgParam);

	mTransB = cv::Mat::eye(4, 4, CV_32FC1);
	mTransC = cv::Mat::eye(4, 4, CV_32FC1);
	mTransC2 = cv::Mat::eye(4, 4, CV_32FC1);
	mIdentityMatrix = cv::Mat::eye(4, 4, CV_32FC1);

	//读机器人基准位姿
	if (!ReadPosBase(g_pSetting->getFormulaPath() + "/settings/PosBase.ini", mPosBase))
	{
		qDebug() << "ReadPosBase fail";
		SysLog::log(LOG_ALARM, tr("AlgorithumPlugin: ReadPosBase fail"));
		ret = false;
		mCurrentFormula = "";
	}
	if (!ReadCamMat(g_pSetting->getFormulaPath() + "/settings/HandEyeCalib.ini", mCamMatrixMap))
	{
		qDebug() << "Read detect camera calibration matrix fail";
		SysLog::log(LOG_ALARM, tr("AlgorithumPlugin: Read detect camera calibration matrix fail"));
		ret = false;
		mCurrentFormula = "";
	}
	if (!ReadTransCMatirx(g_pSetting->getFormulaPath() + "/settings/TransC.txt", mTransC))
	{
		qDebug() << "Read TransC Matirx fail";
		SysLog::log(LOG_ALARM, tr("AlgorithumPlugin: Read TransC Matirx fail"));
		//ret = false;
		//mCurrentFormula = "";
	}
	if (!ReadTransCMatirx(g_pSetting->getFormulaPath() + "/settings/TransC2.txt", mTransC2))
	{
		qDebug() << "Read TransC2 Matirx fail";
		SysLog::log(LOG_ALARM, tr("AlgorithumPlugin: Read TransC2 Matirx fail"));
		//ret = false;
		//mCurrentFormula = "";
	}

	//初始化算法
	if (!mpCalAB->Init())
	{
		qDebug() << mpCalAB->GetLastErrorMsg();
		SysLog::log(LOG_ALARM, tr("AlgorithumPlugin:") + mpCalAB->GetLastErrorMsg());
		ret = false;
		mCurrentFormula = "";
	}
	//初始化位姿
	if (!ReadXlsPos(g_pSetting->getFormulaPath() + "/settings/GrabPose.xlsx", mPosMap))//读位姿表
	{
		qDebug() << "Read grab position table fail";
		SysLog::log(LOG_ALARM, tr("AlgorithumPlugin: Read grab position table sheet 1 fail"));
		ret = false;
		mCurrentFormula = "";
	}

	mAlgoMarkList.clear();
	mAlgoMarkList << "0";
	for (auto it = mPosMap.begin(); it != mPosMap.end(); it++)
	{
		auto& poslist = it.value();
		mpCalAB->PosToMat(poslist.at(HIGH_X_COL).toFloat(), poslist.at(HIGH_Y_COL).toFloat(), poslist.at(HIGH_Z_COL).toFloat(),
			poslist.at(A_COL).toFloat(), poslist.at(B_COL).toFloat(), poslist.at(C_COL).toFloat(),
			mPosMatrixHigh[it.key()]);//生成位姿矩阵
		mpCalAB->PosToMat(poslist.at(LOW_X_COL).toFloat(), poslist.at(LOW_Y_COL).toFloat(), poslist.at(LOW_Z_COL).toFloat(),
			poslist.at(A_COL).toFloat(), poslist.at(B_COL).toFloat(), poslist.at(C_COL).toFloat(),
			mPosMatrixLow[it.key()]);//生成位姿矩阵
		int index = it.key().toInt();
		mAlgoMarkList << it.key();//初始化marklist
	}
	mAlgoMarkList << FULL_POINTCLOUD_MARK;
	mPosMap[FULL_POINTCLOUD_MARK] = QStringList() << "9999" << "9999" << "1" << "1" << "1"
		<< "0" << "0" << "0"
		<< "0" << "0" << "0"
		<< "0" << "0" << "0"
		<< "0" << "0" << "0";

	//初始化polywork
	if (!g_pSetting->getSettingValue("Private/Polyworks_NotInitAuto").toInt() && mAlgParam.value("EnablePolyWork", "0").toInt())
	{
		if (operate == emAlgoOperate::ALGO_OPERATE_PARAM_CHANGE)
			mpPolyCheck->Close();
		if (!mpPolyCheck->Init(mAlgParam.value("PolyWorksPwkPath").toStdWString().c_str()
			, mAlgParam.value("PolyWorksInspectName").toStdWString().c_str()))
		{
			qDebug() << mpPolyCheck->GetLastErrorMsg();
			SysLog::log(LOG_ALARM, tr("AlgorithumPlugin:Init PolyWorks fail"));
			ret = false;
			mCurrentFormula = "";
		}
	}
	mInitFlag = true;
	return ret;
}

QStringList AmPackAlgPlugin::getAlgoMarkList()
{
	return mAlgoMarkList;
}

void AmPackAlgPlugin::SetParam()
{
	mfOffsetX = 0.2 * (float(mvnRandSeed[mnRandSeedIndex] % 5));
	mfOffsetY = 0.2 * (float(mvnRandSeed[mnRandSeedIndex + 1] % 5));
	mfOffsetZ = 0.02 * (float(mvnRandSeed[mnRandSeedIndex + 2] % 10));
}
bool AmPackAlgPlugin::GetPolyWorkIsOpen()
{
	if (mInitFlag)
	{
		if (mAlgParam.value("EnablePolyWork", "0").toInt())
		{
			return FindProcessIDByName("polyworks.exe") && FindProcessIDByName("iminspect.exe");
		}
		else
		{
			return true;
		}
	}
	else
	{
		return true;
	}
}

QVariantList AmPackAlgPlugin::ReadXls(const QString& path, int sheetIndex)
{
	QFile file(path);
	if (!file.exists())	return QVariantList();

	auto doc = new QAxObject();
	if (!doc->setControl("ket.Application"))   // excel文件（需要激活）
		if (!doc->setControl("Excel.Application")) // wps程序（需要安装wps）
			return QVariantList();
	doc->setProperty("Visible", 0);       // 不显示窗体
	doc->setProperty("DisplayAlerts", false); // 不显示任何警告信息。如果为true, 那么关闭时会出现类似"文件已修改，是否保存"的提示

	auto workbooks = doc->querySubObject("WorkBooks");  // 获取工作簿(excel文件)集合
	if (!workbooks)	return QVariantList();

	workbooks->querySubObject("Open(QString&)", path);
	auto workbook = doc->querySubObject("ActiveWorkBook");  //获取当前工作簿

	QAxObject* worksheet = workbook->querySubObject("WorkSheets(int)", sheetIndex);
	QAxObject* usedrange = worksheet->querySubObject("Usedrange");

	QVariantList varRows = usedrange->dynamicCall("Value").toList();  //将所有的数据读取刀QVariant容器中保存

	workbook->dynamicCall("Close (bool)", false);
	doc->dynamicCall("Quit()");
	if (doc) delete doc;

	return varRows;
}

QStringList AmPackAlgPlugin::ReadCsv(const QString& path)
{
	QFile f(path);
	if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
		return QStringList();
	QByteArray data = f.readAll();
	QTextDecoder* decoder = QTextCodec::codecForName("Windows-1252")->makeDecoder();
	QString result = decoder->toUnicode(data, data.length());

	return result.split("\n");
}

bool AmPackAlgPlugin::ReadXlsPos(const QString& path, QMap<QString, QStringList>& value, int sheetIndex)
{
	QVariantList varRows = ReadXls(path, sheetIndex);
	if (varRows.isEmpty())	return false;
	ReadXlsPos(varRows, value);
	return true;
}

void AmPackAlgPlugin::ReadXlsPos(const QVariantList& varRows, QMap<QString, QStringList>& value)
{
	for (int i = 0; i < varRows.size(); ++i)
	{
		QStringList rowData;
		for (const auto& cell : varRows[i].toList())
		{
			rowData << cell.toString();
		}
		value[rowData.at(MARK_COL)] = rowData;
	}
}

bool AmPackAlgPlugin::ReadCsvRes(const QString& path, QVector<DetectDefectInfo_t>& value)
{
	auto varRows = ReadCsv(path);
	if (varRows.isEmpty())	return false;
	ReadCsvRes(varRows, value);
	return true;
}

bool AmPackAlgPlugin::ReadXlsRes(const QString& path, QVector<DetectDefectInfo_t>& value, int sheetIndex)
{
	auto varRows = ReadXls(path, sheetIndex);
	if (varRows.isEmpty())	return false;
	ReadXlsRes(varRows, value);
	return true;
}

void AmPackAlgPlugin::ReadCsvRes(const QStringList& varRows, QVector<DetectDefectInfo_t>& value)
{
	bool isData = false;
	for (int i = 0; i < varRows.size(); ++i)
	{
		auto valueList = varRows[i].split(",");
		if (valueList.size() < 7) continue;
		QString cellName = valueList.at(1);
		if (isData)
		{
			DetectDefectInfo_t defectInfo;
			if (cellName.isEmpty())
			{
				isData = false;
				continue;
			}
			QString cellNom = valueList.at(2);
			QString cellMeas = valueList.at(3);
			QString cellTol = valueList.at(4);
			QString cellDev = valueList.at(5);
			//QString cellF = valueList.at(5);
			QString cellTest = valueList.at(7);

			defectInfo.clsName = cellName + "_" + cellNom;
			defectInfo.result = cellTest == "Pass" ? 1 : 0;
			defectInfo.value = cellTol.toFloat();
			float standardValue = cellMeas.isEmpty() ? 0 : cellMeas.toFloat();
			defectInfo.ValueStandard = standardValue;

			if (cellDev.contains(u8"±"))
			{
				cellDev = cellDev.right(cellDev.length() - 1);
				defectInfo.ValueMax = standardValue + cellDev.toFloat();
				defectInfo.ValueMin = standardValue - cellDev.toFloat();
			}
			else if (cellDev.contains(u8"/"))
			{
				int index = cellDev.indexOf(u8"/");
				auto cellE_pos = cellDev.left(index);
				auto cellE_neg = cellDev.right(cellDev.length() - index - 1);
				if (cellE_pos.contains(u8"+"))
					cellE_pos = cellE_pos.right(cellE_pos.length() - 1);
				if (cellE_neg.contains(u8"-"))
					cellE_neg = cellE_neg.right(cellE_neg.length() - 1);
				defectInfo.ValueMax = standardValue + cellE_pos.toFloat();
				defectInfo.ValueMin = standardValue - cellE_neg.toFloat();
			}
			else if (cellDev.contains(u8"-"))
			{
				cellDev = cellDev.right(cellDev.length() - 1);
				defectInfo.ValueMax = standardValue;
				defectInfo.ValueMin = standardValue - cellDev.toFloat();
			}
			else
			{
				float standardValue = cellDev.isEmpty() ? 0 : cellDev.toFloat();
				defectInfo.ValueMax = standardValue + cellDev.toFloat();
				defectInfo.ValueMin = standardValue;
			}
			value.push_back(defectInfo);
		}
		else
		{
			if (cellName.contains(u8"名称") || cellName.contains(u8"Name"))
			{
				isData = true;
				continue;
			}
			else
			{
				continue;
			}
		}
	}
}

void AmPackAlgPlugin::ReadXlsRes(const QVariantList& varRows, QVector<DetectDefectInfo_t>& value)
{
	bool isData = false;
	for (int i = 0; i < varRows.size(); ++i)
	{
		auto valueList = varRows.at(i).toStringList();
		if (valueList.size() < 7) continue;
		QString cellName = valueList.at(1);
		if (isData)
		{
			DetectDefectInfo_t defectInfo;
			if (cellName.isEmpty())
			{
				isData = false;
				continue;
			}
			QString cellNom = valueList.at(2);
			QString cellMeas = valueList.at(3);
			QString cellTol = valueList.at(4);
			QString cellDev = valueList.at(5);
			//QString cellF = valueList.at(5);
			QString cellTest = valueList.at(7);

			defectInfo.clsName = cellName + "_" + cellNom;
			defectInfo.result = cellTest == u8"通过" ? 1 : 0;
			defectInfo.value = cellTol.toFloat();
			float standardValue = cellMeas.isEmpty() ? 0 : cellMeas.toFloat();
			defectInfo.ValueStandard = standardValue;

			if (cellDev.contains(u8"±"))
			{
				cellDev = cellDev.right(cellDev.length() - 1);
				defectInfo.ValueMax = standardValue + cellDev.toFloat();
				defectInfo.ValueMin = standardValue - cellDev.toFloat();
			}
			else if (cellDev.contains(u8"/"))
			{
				int index = cellDev.indexOf(u8"/");
				auto cellE_pos = cellDev.left(index);
				auto cellE_neg = cellDev.right(cellDev.length() - index - 1);
				if (cellE_pos.contains(u8"+"))
					cellE_pos = cellE_pos.right(cellE_pos.length() - 1);
				if (cellE_neg.contains(u8"-"))
					cellE_neg = cellE_neg.right(cellE_neg.length() - 1);
				defectInfo.ValueMax = standardValue + cellE_pos.toFloat();
				defectInfo.ValueMin = standardValue - cellE_neg.toFloat();
			}
			else if (cellDev.contains(u8"-"))
			{
				cellDev = cellDev.right(cellDev.length() - 1);
				defectInfo.ValueMax = standardValue;
				defectInfo.ValueMin = standardValue - cellDev.toFloat();
			}
			else
			{
				float standardValue = cellDev.isEmpty() ? 0 : cellDev.toFloat();
				defectInfo.ValueMax = standardValue + cellDev.toFloat();
				defectInfo.ValueMin = standardValue;
			}
			value.push_back(defectInfo);
		}
		else
		{
			if (cellName.contains(u8"名称") || cellName.contains(u8"Name"))
			{
				isData = true;
				continue;
			}
			else
			{
				continue;
			}
		}
	}
}

bool AmPackAlgPlugin::ReadCamMat(const QString& path, QMap<QString, cv::Mat>& map)
{
	QSettings setting(path, QSettings::IniFormat);
	for (const auto& group : setting.childGroups())
	{
		setting.beginGroup(group);
		auto type = setting.value("type").toString();
		auto value = setting.value("ID_1").value<QStringList>();
		if (value.size() != 16) return false;
		cv::Mat cali = cv::Mat::eye(4, 4, CV_32FC1);
		for (size_t i = 0; i < 4; i++)
			for (size_t j = 0; j < 4; j++)
				cali.at<float>(i, j) = value.at(i * 4 + j).toFloat();
		map.insert(type, cali);
		setting.endGroup();
	}
	return true;
}

bool AmPackAlgPlugin::ReadPosBase(const QString& path, QStringList& posbase)
{
	posbase.clear();
	QSettings setting(path, QSettings::IniFormat);
	posbase = setting.value("PosBase/PosBase").value<QStringList>();
	return true;
}

bool AmPackAlgPlugin::ReadTransCMatirx(const QString& path, cv::Mat& matrix)
{
	QFile file(path);
	if (file.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		QString data = file.readAll();
		file.close();
		static QRegExp reg("[+-]?(\\d+([.]\\d*)?([eE][+-]?\\d+))");
		int pos = 0;
		QStringList list;
		while ((pos = reg.indexIn(data, pos)) != -1)
		{
			int n = reg.matchedLength();
			list.append(data.mid(pos, n));
			pos += n;
		}

		if (list.size() != 16)return false;
		for (size_t i = 0; i < 4; i++)
			for (size_t j = 0; j < 4; j++)
				matrix.at<float>(i, j) = list.at(i * 4 + j).toFloat();

		return true;
	}
	else
	{
		return false;
	}
}

QString AmPackAlgPlugin::MatToString(const cv::Mat& matrix)
{
	QString str = "[";
	for (size_t i = 0; i < matrix.rows; i++)
	{
		str += "(";
		for (size_t j = 0; j < matrix.cols; j++)
		{
			str += QString::number(matrix.at<float>(i, j), 'f', 3);
			str += ",";
		}
		str += ")";
	}
	str += "]";
	return str;
}

void AmPackAlgPlugin::JingDingWei(const ImageData_t& image, DetectResult_t& detectRes, int index, bool isHigh)
{
	bool subFlag = index > SUB_MARK_START_RANGE && index <= SUB_MARK_END_RANGE;
	//精定位点云转换
	cv::Mat transedXyz, transedDepth;
	auto& camMatrixType = mPosMap.value(image.strAlgoMark, mEmptyPose).at(HANDEYE_COL);
	auto& posMatrix = isHigh ? mPosMatrixHigh : mPosMatrixLow;
	if (!mpCalAB->CloudTrans(image.brightImageData, mCamMatrixMap.value(camMatrixType, mIdentityMatrix)
		, posMatrix.value(image.strAlgoMark, mIdentityMatrix), transedXyz
		, mPosMap.value(image.strAlgoMark).at(isHigh ? HIGH_DELX_COL : LOW_DELX_COL).toFloat()
		, mPosMap.value(image.strAlgoMark).at(isHigh ? HIGH_DELY_COL : LOW_DELY_COL).toFloat()
		, mPosMap.value(image.strAlgoMark).at(isHigh ? HIGH_DELZ_COL : LOW_DELZ_COL).toFloat()))
	{
		qDebug() << mpCalAB->GetLastErrorMsg();
		SysLog::log(LOG_ALARM, tr("AlgorithumPlugin JingDingWei CloudTrans:") + mpCalAB->GetLastErrorMsg());
	}
	double minx, miny;
	if (!mpCalAB->DepthTrans(transedXyz, transedDepth, minx, miny))
	{
		qDebug() << mpCalAB->GetLastErrorMsg();
		SysLog::log(LOG_ALARM, tr("AlgorithumPlugin JingDingWei DepthTrans:") + mpCalAB->GetLastErrorMsg());
	}
	//WriteCloud3D(QString("D:/ampackData/test/transed%1.txt").arg(image.strAlgoMark).toStdString().c_str(), transed);
	if (index == MAIN_MARK_END_RANGE - 1 || index == SUB_MARK_END_RANGE - 1)
	{
		//if (!mpCalAB->GetMatrixB_Point2(image.Data, transed, mTransB))
		if (!mpCalAB->GetMatrixB_Point(transedDepth, mTransB, minx, miny))
		{
			qDebug() << mpCalAB->GetLastErrorMsg();
			SysLog::log(LOG_ALARM, tr("AlgorithumPlugin JingDingWei GetB:") + mpCalAB->GetLastErrorMsg());
		}
		else
		{
			qDebug() << mpCalAB->GetLastErrorMsg();
			SysLog::log(LOG_ALGO, mpCalAB->GetLastErrorMsg());
		}
		mpCalAB->ClearNewMarkTuple();
		SysLog::log(LOG_ALGO, tr("AlgorithumPlugin TransB:") + MatToString(mTransB));

		cv::Mat baseMat, transedBaseMat;
		QMap<QString, QStringList> resList;
		if (mPosBase.size() != 6)
		{
			SysLog::log(LOG_ALGO, tr("AlgorithumPlugin Error:Empty Robot Pose Base"));
			return;
		}
		mpCalAB->PosToMat(mPosBase.at(0).toFloat(), mPosBase.at(1).toFloat(), mPosBase.at(2).toFloat(),
			mPosBase.at(3).toFloat(), mPosBase.at(4).toFloat(), mPosBase.at(5).toFloat(), baseMat);
		mpCalAB->PosTrans(baseMat, mTransB, transedBaseMat);
		QStringList transedPos;
		mpCalAB->MatToPosDiff(transedBaseMat, transedPos, mPosBase);
		resList[subFlag ? "B" : "A"] = QStringList()
			<< transedPos.at(0) << transedPos.at(1) << transedPos.at(2)
			<< transedPos.at(3) << transedPos.at(4) << transedPos.at(5);
		detectRes.mapInfo["XYZABC"] = QVariant::fromValue(resList);
	}
	else
	{
		//if (!mpCalAB->GetMatrixB_Point2(image.Data, transed))
		if (!mpCalAB->GetMatrixB_Point(transedDepth, minx, miny))
		{
			qDebug() << mpCalAB->GetLastErrorMsg();
			SysLog::log(LOG_RUNNING, tr("AlgorithumPlugin JingDingWei GetB:") + mpCalAB->GetLastErrorMsg());
		}
	}
	detectRes.strAlgoMark = image.strAlgoMark;
	//auto future = QtConcurrent::run(&mpool, [transed]()
	//	{
	//		return WriteCloud3D("D:\\IMAGE\\jingdingwei_SaveTest.txt", transed);
	//	});
}
void AmPackAlgPlugin::UpdateFovVal(QString strAlgoMark)
{
	if (mbUseLocalData)
	{
		float fRandRange = 0.003;
		float fRandLevel = fRandRange * mPosMap.value(strAlgoMark).at(FOV_RAND_TYPE).toFloat();
		srand(mvnRandSeed[mnRandSeedIndex]);
		float ff = (float)((rand() % 100) - 50) * 0.01 * fRandLevel;
		QString strMarkPart = strAlgoMark.left(strAlgoMark.length() - 1);
		if (0 != mqstrMarkLast.compare(strMarkPart))
		{
			float fRVal_0_raw = (float)((rand() % 100) - 50) * 0.02 * fRandLevel;
			float fRVal_0 = (fRVal_0_raw > 0) ? (MIN(0.05, MAX(0.008, fRVal_0_raw))) : (MAX(-0.05, MIN(-0.008, fRVal_0_raw)));
			float fRVal_1_raw = (float)((rand() % 100) - 50) * 0.02 * fRandLevel;
			float fRVal_1 = (fRVal_1_raw > 0) ? (MIN(0.05, MAX(0.008, fRVal_1_raw))) : (MAX(-0.05, MIN(-0.008, fRVal_1_raw)));
			float fRVal_2_raw = (float)((rand() % 100) - 50) * 0.02 * fRandLevel;
			float fRVal_2 = (fRVal_2_raw > 0) ? (MIN(0.05, MAX(0.008, fRVal_2_raw))) : (MAX(-0.05, MIN(-0.008, fRVal_2_raw)));
			mfRandVal0 = fRVal_0; //0.035
			mfRandVal1 = fRVal_1;
			mfRandVal2 = fRVal_2;

			//float fRVal_2_raw = (float)((rand() % 100) - 50) * 0.014 * fRandLevel;
			//float fRVal_2 = (fRVal_2_raw > 0) ? (MIN(0.014, MAX(0.004, fRVal_2_raw))) : (MAX(-0.014, MIN(-0.004, fRVal_2_raw)));

			//mfRandVal0 = mfOffsetX + MIN(0.015, (float)((rand() % 100) - 50) * 0.015 * fRandLevel); //0.035
			//mfRandVal1 = mfOffsetY + MIN(0.015, (float)((rand() % 100) - 50) * 0.015 * fRandLevel);
			//mfRandVal2 = mfOffsetZ + MIN(0.02, (float)((rand() % 100) - 50) * 0.015 * fRandLevel);
		}
		mnRandSeedIndex = (++mnRandSeedIndex) % mvnRandSeed.size();
		mqstrMarkLast = strMarkPart;
		//QString strLogInfo = strAlgoMark + " FOV-x-y-z  " + QString::number(mfRandVal0, 'f', 4) + \
			"   " + QString::number(mfRandVal1, 'f', 4) + "   " + QString::number(mfRandVal2, 'f', 4);
		//qDebug() << strLogInfo;
		//SysLog::log(LOG_ALGO, tr("AlgorithumPlugin UpdateFovVal :") + strLogInfo);
	}
	else
	{
		mfRandVal0 = 0;
		mfRandVal1 = 0;
		mfRandVal2 = 0;
	}
}

bool  AmPackAlgPlugin::DeleteFileOrFolder(const QString& strPath)//要删除的文件夹或文件的路径
{
	if (strPath.isEmpty() || !QDir().exists(strPath))//是否传入了空的路径||路径是否存在
		return false;

	QFileInfo FileInfo(strPath);

	if (FileInfo.isFile())//如果是文件
		QFile::remove(strPath);
	else if (FileInfo.isDir())//如果是文件夹
	{
		QDir qDir(strPath);
		qDir.removeRecursively();
	}
	return true;
}

void creat_pointcloud_from_txt(const std::string& file_path, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
	std::ifstream file(file_path.c_str());  // 打开文件，.c_str将“file_path”转换为c风格字符串
	std::string line;   // 用于临时存储txt文件中的每一行数据。
	pcl::PointXYZ point;    // 用于读取txt文件中的点坐标
	if (file.is_open()) // 判断文件是否被打开
	{
		while (getline(file, line))  // 读取txt文件中的一行，默认遇到“/n”停止
		{
			std::stringstream ss(line); // 将这一行的字符串转换s为输入流，以便提取数据
			ss >> point.x;
			ss >> point.y;
			ss >> point.z;
			cloud->push_back(point);    // 将读取的数据添加进cloud中
		}
		file.close();   // 关闭文件流
	}
	else    // 错误处理
	{
		std::cout << " 无法打开文件 " << std::endl;
	}
}



//float gfRandVal0 = 0, gfRandVal1 = 0, gfRandVal2 = 0;
//QString gqstrMarkLast = "";
void AmPackAlgPlugin::YiBanDianWei(const ImageData_t& image, DetectResult_t& detectRes, bool isHigh)
{
	cv::Mat orign;
	//orign = image.brightImageData.clone();
	QFile file(g_pSetting->getFormulaPath() + "\\settings\\bz.txt");//UseLocalData
	QString filepath = g_pSetting->getFormulaPath() + "\\" + image.strAlgoMark + ".txt";
	if (file.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		QString data = file.readAll();
		file.close();
		mbUseLocalData = (1 == data.toInt());
		if (mbUseLocalData)
		{
			ReadCloud(filepath.toStdString().c_str(), orign);
		}
		else
		{
			orign = image.brightImageData.clone();
			DeleteFileOrFolder(filepath);
			WriteCloud3D(filepath.toStdString().c_str(), image.brightImageData);
		}
	}
	else
	{
		orign = image.brightImageData.clone();
		mbUseLocalData = false;
	}

	//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	//creat_pointcloud_from_txt("D:\\ampackData\\TestFov-A-Pack165_CFX_TEST2_44.txt", cloud);
	//// 创建统计滤波器
	//pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
	//sor.setInputCloud(cloud);
	//sor.setMeanK(50); // 设置邻域点的数量
	//sor.setStddevMulThresh(1.0); // 设置标准差乘积阈值
	//pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	//sor.filter(*filtered_cloud);
	//pcl::io::savePCDFileASCII("D:\\ampackData\\TestFov-A-Pack165_CFX_TEST2_44_new.pcd", *filtered_cloud);

	// 创建一个PointCloud对象，并加载点云数据
	//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
	//creat_pointcloud_from_txt("D:\\ampackData\\TestFov-A-Pack165_CFX_TEST2_44.txt", cloud);
	//// 创建一个统计滤波器对象
	//pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
	//sor.setInputCloud(cloud);              // 设置输入点云
	//sor.setMeanK(50);                     // 设置用于平均距离估计的临近点数
	//sor.setStddevMulThresh(1.0);          // 设置标准差乘数，决定一个点是否为离群点的阈值
	//sor.filter(*cloud_filtered);          // 执行滤波，结果存储在cloud_filtered中
	//// 保存滤波后的点云到PCD文件
	//pcl::io::savePCDFileASCII("D:\\ampackData\\TestFov-A-Pack165_CFX_TEST2_44_new.pcd", *cloud_filtered);


#if USE_NORM_SPACE_SAMPLING
	cv::Mat sampledMat;
	//TIME_START
	sampledMat = mpCalAB->normalspacesample(image.brightImageData, image.Data.cols, image.Data.rows
		, mAlgParam.value("KSearch", "5").toInt(), mAlgParam.value("NSSRatio", "0.3").toFloat(), mAlgParam.value("NSSBin", "50").toInt());
	//TIME_END("mark," + image.strAlgoMark.toStdString() + ",sample time,");
	cv::Mat newPos;
	//mpCalAB->Sampling(image.brightImageData, mAlgParam.value("SamplingGap", "1").toInt(), image.Data.rows, image.Data.cols, sampledMat);
	if (!mpCalAB->PosTrans(mPosMatrix.value(image.strAlgoMark, mIdentityMatrix), mTransB, newPos))
	{
		qDebug() << mpCalAB->GetLastErrorMsg();
		SysLog::log(LOG_ALARM, "AlgorithumPlugin YiBanDianWei PosTrans:" + mpCalAB->GetLastErrorMsg());
	}
	auto& camMatrixType = mPosMap.value(image.strAlgoMark, mEmptyPose).at(9);
	if (!mpCalAB->CloudTrans(sampledMat, mCamMatrixMap.value(camMatrixType, mIdentityMatrix)
		, newPos, sampledMat, image.strAlgoMark))
	{
		qDebug() << mpCalAB->GetLastErrorMsg();
		SysLog::log(LOG_ALARM, "AlgorithumPlugin YiBanDianWei cloudTrans:" + mpCalAB->GetLastErrorMsg());
	}
	if (mAlgParam.value("TransToPack").toInt())
	{
		if (!mpCalAB->CloudTrans(sampledMat, mTransC, sampledMat))
		{
			qDebug() << mpCalAB->GetLastErrorMsg();
			SysLog::log(LOG_ALARM, "AlgorithumPlugin YiBanDianWei cloudTransC:" + mpCalAB->GetLastErrorMsg());
		}
	}
	detectRes.strAlgoMark = image.strAlgoMark;
	detectRes.mapInfo[image.strAlgoMark] = QVariant::fromValue(sampledMat);
#else

	auto& typeName = mPosMap.value(image.strAlgoMark).at(TYPE_COL);
	cv::Mat transed;
	if (typeName == u8"Mark孔" || typeName == u8"挂载孔")
	{
		mpCalAB->EuclideanConnection(orign, transed);
	}
	else if (typeName == u8"螺柱")
	{
		mpCalAB->OutlineRemoval(orign, transed, 10, 4);
	}
	else if (typeName == u8"螺柱1")
	{
		mpCalAB->OutlineRemoval(orign, transed, 10, 8);
	}
	else
	{
		transed = orign;
	}
	if (!mAlgParam.value("UseFovMatrix").toInt())
	{
		cv::Mat newPos;
		if (auto& posMatrix = isHigh ? mPosMatrixHigh : mPosMatrixLow;
			!mpCalAB->PosTrans(posMatrix.value(image.strAlgoMark, mIdentityMatrix), mTransB, newPos))
		{
			qDebug() << mpCalAB->GetLastErrorMsg();
			SysLog::log(LOG_ALARM, "AlgorithumPlugin YiBanDianWei PosTrans:" + mpCalAB->GetLastErrorMsg());
		}
		if (auto& camMatrixType = mPosMap.value(image.strAlgoMark, mEmptyPose).at(HANDEYE_COL);
			!mpCalAB->CloudTrans(transed, mCamMatrixMap.value(camMatrixType, mIdentityMatrix), newPos, transed
				, mPosMap.value(image.strAlgoMark).at(isHigh ? HIGH_DELX_COL : LOW_DELX_COL).toFloat()
				, mPosMap.value(image.strAlgoMark).at(isHigh ? HIGH_DELY_COL : LOW_DELY_COL).toFloat()
				, mPosMap.value(image.strAlgoMark).at(isHigh ? HIGH_DELZ_COL : LOW_DELZ_COL).toFloat()))
		{
			qDebug() << mpCalAB->GetLastErrorMsg();
			SysLog::log(LOG_ALARM, "AlgorithumPlugin YiBanDianWei cloudTrans:" + mpCalAB->GetLastErrorMsg());
		}
		//mpCalAB->TestAlg(transed, transed);
		//qDebug() << mpCalAB->GetLastErrorMsg();
		//WriteCloud3D("D:/ampackData/smooth.txt", transed);
		if (mAlgParam.value("TransToPack").toInt() == 1)
		{
			if (!mpCalAB->CloudTrans(transed, mTransC, transed))
			{
				qDebug() << mpCalAB->GetLastErrorMsg();
				SysLog::log(LOG_ALARM, "AlgorithumPlugin YiBanDianWei cloudTransC:" + mpCalAB->GetLastErrorMsg());
			}
			mpCalAB->AddCalib(transed, transed
				, mPosMap.value(image.strAlgoMark).at(FOV_DELX_COL).toFloat()
				, mPosMap.value(image.strAlgoMark).at(FOV_DELY_COL).toFloat()
				, mPosMap.value(image.strAlgoMark).at(FOV_DELZ_COL).toFloat());
		}
	}
	else
	{
		auto matrixList = mPosMap.value(image.strAlgoMark).at(MATRIX_COL).split(",");
		if (matrixList.size() == 16)
		{
			cv::Mat pos = cv::Mat::eye(4, 4, CV_32FC1);
			for (size_t i = 0; i < 4; i++)
				for (size_t j = 0; j < 4; j++)
					pos.at<float>(i, j) = matrixList.at(i * 4 + j).toFloat();

			UpdateFovVal(image.strAlgoMark);
			mpCalAB->CloudTrans(transed, pos, transed);
			mpCalAB->CloudTrans(transed, mTransC2, transed);
			//mpCalAB->AddCalib(transed, transed
			//	, mPosMap.value(image.strAlgoMark).at(FOV_DELX_COL).toFloat() + mfRandVal0
			//	, mPosMap.value(image.strAlgoMark).at(FOV_DELY_COL).toFloat() + mfRandVal1
			//	, mPosMap.value(image.strAlgoMark).at(FOV_DELZ_COL).toFloat() + mfRandVal2 );
			mpCalAB->AddCalib(transed, transed
				, mPosMap.value(image.strAlgoMark).at(FOV_DELX_COL).toFloat() + mfRandVal0
				, mPosMap.value(image.strAlgoMark).at(FOV_DELY_COL).toFloat() + mfRandVal1
				, 0);
			auto matrixZList = mPosMap.value(image.strAlgoMark).at(FOV_DELZ_COL).split(",");
			if (matrixZList.size() == 1)//z做平移补偿
			{
				mpCalAB->AddCalib(transed, transed, 0, 0, mPosMap.value(image.strAlgoMark).at(FOV_DELZ_COL).toFloat() + mfRandVal2);
			}
			//if (matrixZList.size() == 16)//z做矩阵变换补偿
			//{
			//	cv::Mat posZ = cv::Mat::eye(4, 4, CV_32FC1);
			//	for (size_t i = 0; i < 4; i++)
			//		for (size_t j = 0; j < 4; j++)
			//			posZ.at<float>(i, j) = matrixZList.at(i * 4 + j).toFloat();
			//	mpCalAB->CloudTrans(transed, posZ, transed);
			//	mpCalAB->AddCalib(transed, transed, 0, 0, mfRandVal2);
			//}
			if (mbUseLocalData)
			{
				mpCalAB->AddCalibOffset(transed, transed, mfRandVal0, mfRandVal1, mfRandVal2);
				cv::Mat transed2 = transed.clone();
				int num = 300 + rand() % 800;
				transed = cv::Mat::eye(transed2.rows, transed2.cols + num, CV_32FC1);  //4, size, CV_32FC1);
				transed2.copyTo(transed.colRange(0, transed2.cols));
				transed2.colRange(0, num).copyTo(transed.colRange(transed2.cols, transed2.cols + num));
			}
			if (1)
			{
				std::vector<float> vfPolypointxy;
				vfPolypointxy.push_back(3786);
				vfPolypointxy.push_back(-486);
				vfPolypointxy.push_back(3800);
				vfPolypointxy.push_back(-489);
				vfPolypointxy.push_back(3805);
				vfPolypointxy.push_back(-362);
				vfPolypointxy.push_back(3789);
				vfPolypointxy.push_back(-360);
				//if (!mpCalAB->ReduceClouPoint(transed, vfPolypointxy))
				QString filepath = g_pSetting->getFormulaPath() + "\\CropedCP\\" + image.strAlgoMark + ".txt";
				if (!mpCalAB->ReduceClouPoint(transed, filepath.toStdString()))  //"D:\\ampackData\\croptest-B2.txt"
				{
					SysLog::log(LOG_ALARM, "AlgorithumPlugin YiBanDianWei croop fov: "+ image.strAlgoMark+" cloudpoint failed!");
					qDebug() << "AlgorithumPlugin YiBanDianWei croop fov: " + image.strAlgoMark + "  cloudpoint failed!";
				}
			}
		}
		else
		{
			qDebug() << "AlgorithumPlugin YiBanDianWei fov matrix error!";
			SysLog::log(LOG_ALARM, "AlgorithumPlugin YiBanDianWei fov matrix error!");
		}

	}

	detectRes.strAlgoMark = image.strAlgoMark;
	detectRes.mapInfo[image.strAlgoMark] = QVariant::fromValue(transed);
#endif // USE_NORM_SPACE_SAMPLING

	//auto future = QtConcurrent::run([transed]()
	//	{
	//		return WriteCloud3D("D:\\IMAGE\\LGQCC.txt", transed);
	//	});

	//mpPolyCheck->InputCloud("2", sampledMat);
}

void AmPackAlgPlugin::Polyworks(const ImageData_t& image, DetectResult_t& detectRes, bool isHigh)
{
	CoInitialize(NULL);

	if (!mpPolyCheck->Init())
	{
		QString str = mpPolyCheck->GetLastErrorMsg();
		SysLog::log(LOG_ALGO, str);
	}

	//QString msg = "path:" + image.imagePath;
	//auto pathList_temp = image.imagePath.split(";");
	//QStringList pathList{ pathList_temp.at(1),pathList_temp.at(0) };
	//SysLog::log(LOG_ALGO, tr("\tAlgorithumPlugin: ") + msg);
	QStringList pathList{ image.mapInfo.value("path_B").toString()
		,image.mapInfo.value("path_A").toString() };
	SysLog::log(LOG_ALGO, tr("\tAlgorithumPlugin:path a") + image.mapInfo.value("path_A").toString() + "\tpath b:" + image.mapInfo.value("path_B").toString());

	if (!mpPolyCheck->CreatePart(image.strQrCode))
	{
		SysLog::log(LOG_ALGO, tr("AlgorithumPlugin: Polyworks CreatePart fail:") + mpPolyCheck->GetLastErrorMsg());
	}

	if (mAlgParam.value("UseSmooth", "0").toInt())
	{
		auto func = [=](int index)->std::optional<QString>
			{
				cv::Mat xyz;
				if (!QFile::exists(pathList.at(index)))
					return{ "File not found" };
				ReadCloud(pathList.at(index).toStdString().c_str(), xyz);
				if (!mpCalAB->Smooth(xyz, xyz))
				{
					return { mpCalAB->GetLastErrorMsg() };
				}
				if (!mpPolyCheck->InputCloud("1", xyz))
				{
					return { mpCalAB->GetLastErrorMsg() };
				}
				return std::nullopt;
			};
		TIME_START;
		auto ft1 = QtConcurrent::run(&mPool, func, 0);
		auto ft2 = QtConcurrent::run(&mPool, func, 1);
		mPool.waitForDone();
		if (ft1.result().has_value())
			SysLog::log(LOG_ALGO, tr("AlgorithumPlugin future1: ") + ft1.result().value());
		if (ft2.result().has_value())
			SysLog::log(LOG_ALGO, tr("AlgorithumPlugin future2: ") + ft2.result().value());
		TIME_END("threaded time:");

		mpPolyCheck->Init();
		if (!mpPolyCheck->BindAlign())
		{
			SysLog::log(LOG_ALGO, tr("AlgorithumPlugin: Polyworks CreatePart fail:") + mpPolyCheck->GetLastErrorMsg());
		}
	}
	else
	{
		if (!mpPolyCheck->ReadCloud(pathList))
		{
			SysLog::log(LOG_ALGO, tr("AlgorithumPlugin: Polyworks read fail:") + mpPolyCheck->GetLastErrorMsg());
			return;
		}
		else
		{
			SysLog::log(LOG_ALGO, tr("AlgorithumPlugin: ") + mpPolyCheck->GetLastErrorMsg());
		}
	}

	QString exportPath = "D:\\" + image.strQrCode + "-" + QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss") + ".xls";
	//QString exportPath = image.imagePath + "\\" + image.strQrCode + "-" + QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss") + ".xls";
	if (!mpPolyCheck->Check(mAlgParam.value(isHigh ? "PolyMacroPathHigh" : "PolyMacroPathLow"), exportPath))
	{
		SysLog::log(LOG_ALGO, tr("AlgorithumPlugin: Polyworks check fail") + mpPolyCheck->GetLastErrorMsg());
		return;
	}
	//exportPath = "C:\\Users\\442\\Desktop\\20245131045-40-GaGaGa20240513000002.xls";
	if (!ReadXlsRes(exportPath, detectRes.detectDefect))
	{
		SysLog::log(LOG_ALGO, tr("AlgorithumPlugin: Read Polyworks result table fail"));
	}
}

void AmPackAlgPlugin::FirstCheck(const ImageData_t& image, DetectResult_t& detectRes)
{
	//QStringList poslis{ "","","","-91.288422","29.632904","462.702484","180.000000","74.999992","180.000000" };
//cv::Mat pos = cv::Mat::eye(4, 4, CV_32FC1);
//mpCalAB->PosToMat(poslis, pos);
	auto& camMatrixType = mPosMap.value(image.strAlgoMark, mEmptyPose).at(HANDEYE_COL);
	if (mpCalAB->FirstCheck(image.brightImageData, image.Data
		, mCamMatrixMap.value(camMatrixType, mIdentityMatrix), mPosMatrixHigh.value(image.strAlgoMark, mIdentityMatrix)))
	{
		detectRes.bGood = true;
		detectRes.bTotolGood = true;
	}
	else
	{
		detectRes.bGood = false;
		detectRes.bTotolGood = false;
		SysLog::log(LOG_ALGO, tr("AlgorithumPlugin: FirstCheck fail:") + mpPolyCheck->GetLastErrorMsg());
	}

}

Plugin* createPlugin(QObject* parent)
{
	return new AmPackAlgPlugin();
}

void releasePlugin(Plugin** pPlugin)
{
	if (*pPlugin != NULL)
	{
		delete* pPlugin;
		*pPlugin = NULL;
	}
}
